#include <VortexManipulator.h>

int cycle = 0;
unsigned long lastEventMicros=0;
IntervalTimer myTimer;

void checkPulse() { // triggered when Timer fires
	cli();
	// disable interrupts while we do this
	int signal = analogRead(PULSE_PIN); // read the Pulse Sensor
	heartRateInterrupt.calculate(signal);
	sei();

} // end isr
void setup() {
	setSyncProvider((getExternalTime)Teensy3Clock.get);
	Serial.begin(9600);
	delay(5000);
#ifdef VORTEXMANIPULATOR_DEBUG
	Serial.println("starting...");
#endif
	Hardware.init();
	configuration.load();
	Appregistry.init();
//	analogReference(EXTERNAL);

//	Appregistry.setCurrentApp(Appregistry.getApp("Menu"));

//	FlexiTimer2::set(2, 1.0 / 1000, checkPulse); // call every 2ms "ticks"
//	FlexiTimer2::start();
	myTimer.begin(checkPulse,2000);
}

void loop() {
	cycle++;

	digitalWrite(13, HIGH);
	Point p = Touchscreen.getPoint();
	digitalWrite(13, LOW);
	pinMode(XP, OUTPUT);
	pinMode(XM, OUTPUT);
	pinMode(YP, OUTPUT);
	pinMode(YM, OUTPUT);
	if (p.z > MINPRESSURE && p.z < MAXPRESSURE) {
#ifdef VORTEXMANIPULATOR_DEBUG
		Serial.print(PSTR("loop:touch(raw) "));
		Serial.print(p.x);
		Serial.print(BLANK);
		Serial.print(p.y);
		Serial.print(BLANK);
		Serial.print(p.z);
		Serial.print(PSTR(" rotation: "));
		Serial.println(Graphics.getRotation());
#endif
		int x = 0;
		int y = 0;
		cycle = 0; // Ensure we don't sleep if we are operating.

		switch (Graphics.getRotation()) {
		case 0:
			y = map(p.x,TS_MINX, TS_MAXX, Graphics.width(), 0);
			x = Graphics.height() - map(p.y, TS_MINY, TS_MAXY, Graphics.height(), 0);
			break;
		case 1:
			// TODO:
			break;
		case 2:
			// TODO:
			break;
		case 3:
			y = map(p.x,TS_MINX, TS_MAXX, Graphics.height(), 0);
#ifdef VORTEXMANIPULATOR_DEBUG
			Serial.print(PSTR("rotation "));
			Serial.print(p.y);
			Serial.print(BLANK);
			Serial.print(TS_MINY);
			Serial.print(BLANK);
			Serial.print(TS_MAXY);
			Serial.print(BLANK);
			Serial.print(Graphics.width());
			Serial.print(BLANK);
			Serial.println(map(p.y, TS_MINY, TS_MAXY, Graphics.width(), 0));
#endif
			x = Graphics.width() - map(p.y, TS_MINY, TS_MAXY, Graphics.width(), 0);
			break;
		}
#ifdef VORTEXMANIPULATOR_DEBUG
		Graphics.fillRect(0,0,Graphics.width(),10,BLACK);
		Graphics.setCursor(0,0);
		Graphics.print(PSTR("raw "));
		Graphics.print(p.x);
		Graphics.print(BLANK);
		Graphics.print(p.y);
		Graphics.print(PSTR(" adj "));
		Graphics.print(x);
		Graphics.print(BLANK);
		Graphics.print(y);
		Graphics.print(PSTR(" w: "));
		Graphics.print(Graphics.width());
		Graphics.print(PSTR(" h: "));
		Graphics.print(Graphics.height());
		Graphics.print(PSTR(" r: "));
		Graphics.print(Graphics.getRotation());
#endif
		p.x = x;
		p.y = y;
#ifdef VORTEXMANIPULATOR_DEBUG
		Serial.print(PSTR("loop:touch(revised) "));
		Serial.print(p.x);
		Serial.print(BLANK);
		Serial.println(p.y);
#endif
		if (p.x<10) {
#ifdef VORTEXMANIPULATOR_DEBUG
			Serial.println(PSTR("(main)Switching to menu"));
#endif
			Appregistry.jumpToMenu();
			return;
		}
		if (!Appregistry.getCurrentApp()->touch(p)) {
			Appregistry.jumpToMenu();
			return;
		}
	}
	unsigned long m = micros();
	if ((m-lastEventMicros) > Appregistry.getCurrentApp()->getUpdateInterval()) {
		Appregistry.getCurrentApp()->display();
		lastEventMicros = m;
	}

	// if we pass max cycles then invoke the shutdown.
	if (cycle > MAX_CYCLE) {
#ifdef VORTEXMANIPULATOR_DEBUG
		Serial.println(PSTR("shutdown"));
#endif
		Hardware.shutdown();

		cycle = 0; // if we get here then start again.
		Appregistry.getCurrentApp()->setup();
		Appregistry.getCurrentApp()->display();
	}

	delay(LOOP_DELAY);
}
#ifdef __cplusplus
int main(void) {
	_init_Teensyduino_internal_();

	setup();

	while (1) {
		loop();
	}
}
#endif
